#include "Unit.h"

using namespace std;

Unit::Unit()
{
    type = "missing";
    initFromFile();
    xVelocity = 0;
    yVelocity = 0;
    xAcc = 0;
    yAcc = 0;
    facing_left = false;
    jump_dist = 600;
    walljump = 0;
}

Unit::Unit(Artist& artist, string Type)
{
    type = Type;
    jump_dist = 600;
    walljump = 0;
    initFromFile();
    set_image(artist);
    img.frameSplice(bounds.w, bounds.h);
    xVelocity = 0;
    yVelocity = 0;
    xAcc = 0;
    yAcc = 0;
    facing_left = false;
}

Unit::Unit(Unit& clone)
{
    bounds = *clone.get_bounds();
    hp = clone.get_hp();
    maxHp = hp;
    weight = clone.get_weight();
    speed = clone.get_speed();
}

void Unit::initFromFile()
{
    string filepath = "data/units/" + type + ".unit";

    cout << "Loading unit " << filepath << "\n";

    ifstream unitFile(filepath.c_str(), ifstream::in);

    if(unitFile != NULL)
    {
        cout << "ifstream successfull, loading unit.\n";

        string tag = "";
        string line = "";
        while(getline(unitFile, line))
        {
            if(line == "" || line==" " || line[0]==';')
            {

            }
            else if(line[0] == '[')
            {
                tag = line.substr(1, line.find_first_of("]") - 1);
            }
            else
            {
                string key = line.substr(0, line.find_first_of("="));
                string value = line.substr(line.find_first_of("=") + 1);
                if(tag=="stats")
                {
                    if(key == "hp")
                    {
                        hp = atoi(value.c_str());
                        maxHp = hp;
                        cout << "hp set to " << hp <<"\n";
                    }
                    else if(key == "size")
                    {
                        bounds.x=0;
                        bounds.y=0;
                        bounds.w = atoi(value.c_str());
                        bounds.h = bounds.w;
                        cout << "size set to " << bounds.w << ", " << bounds.h << "\n";
                    }
                    else if(key == "weight")
                    {
                        weight = atoi(value.c_str());
                        cout << "weight set to " << weight << "\n";
                    }

                }
                else if (tag == "move")
                {
                    if(key == "speed")
                    {
                        speed = atoi(value.c_str());
                        cout << "speed set to " << speed << "\n";
                    }
                    else if(key == "jump")
                    {
                        jump_dist = atoi(value.c_str());
                        cout << "jump velocity set to " << jump_dist << "\n";
                    }
                    else if(key == "walljump")
                    {
                        walljump = atoi(value.c_str());
                        cout << "walljump set to " << walljump << "\n";
                    }
                }
                else
                    cout << "skipping unknown tag \"" << tag << "\"\n\n";
            }
        }
    }
}

void Unit::clone(Unit& clone)
{
    *this = clone;
}

Unit Unit::operator=(Unit& clone)
{
    bounds = *clone.get_bounds();
    hp = clone.get_hp();
    maxHp = hp;
    weight = clone.get_weight();
    speed = clone.get_speed();

    return *this;
}

Unit::~Unit()
{
}

void Unit::set_hp(int h)
{
    hp = h;
}

void Unit::set_maxHp(int mh)
{
    maxHp = mh;
}

void Unit::set_weight(int w)
{
    weight = w;
}

void Unit::rotateSprite(Artist& artist, Direction dir)
{
    img.rotateSprite(artist, dir, true);
}

void Unit::display(SDL_Rect camera, SDL_Surface* screen)
{
    img.display(screen, facing_left, bounds.x - camera.x, bounds.y - camera.y);
}

void Unit::set_image(Artist& artist, string filepath)
{
    if(filepath == "" && type!="")
        filepath = "unit/" + type + ".png";


    img.setImage(artist, filepath, true, true);
}

int Unit::get_hp()
{
    return hp;
}

int Unit::get_maxHp()
{
    return maxHp;
}

int Unit::get_weight()
{
    return weight;
}

int Unit::get_speed()
{
    return speed;
}

int Unit::get_walljump()
{
    return walljump;
}

SDL_Rect* Unit::get_bounds()
{
    return &bounds;
}


void Unit::take_damage(int damage)
{
    if(maxHp > 0)
    {
        hp -= damage;
    }
}

void Unit::inc_x(int amount)
{
    bounds.x += amount;
}

void Unit::inc_y(int amount)
{
    bounds.y += amount;
}


int Unit::getXVelocity()
{
    return xVelocity;
}

int Unit::getYVelocity()
{
    return yVelocity;
}

int Unit::get_xAcc()
{
    return xAcc;
}

int Unit::get_yAcc()
{
    return yAcc;
}

void Unit::setXVelocity(int amount)
{
    xVelocity = amount;
}

void Unit::setYVelocity(int amount)
{
    yVelocity = amount;
}

void Unit::setXAcc(int amount)
{
    xAcc = amount;
}

void Unit::setYAcc(int amount)
{
    yAcc = amount;
}

void Unit::incXVelocity(int amount)
{
    xVelocity += amount;
}

void Unit::incYVelocity(int amount)
{
    yVelocity += amount;
}

void Unit::teleport(SDL_Rect box)
{
    bounds.x = box.x;
    bounds.y = box.y;
}

void Unit::teleport(int x, int y)
{
    bounds.x = x;
    bounds.y = y;
}

SDL_Rect Unit::get_move(Direction dir, int amount)
{
    SDL_Rect box = bounds;

    if(weight>0)
    {
        switch(dir)
        {
            case LEFT: box.x-=amount; break;
            case RIGHT: box.x+=amount; break;
            case DOWN: box.y+=amount; break;
            case UP: box.y-=amount; break;
        }
    }

    return box;
}

void Unit::move(Direction dir, int amount)
{
    switch(dir)
    {
        case UP: bounds.y -= amount; break;
        case DOWN: bounds.y += amount; break;
        case RIGHT: bounds.x += amount; break;
        case LEFT: bounds.x -= amount; break;
    }
}

SDL_Rect Unit::fall(Direction grav, int gravity)
{
    SDL_Rect box = bounds;

    if(weight>0)
    {
        switch(gravity)
        {
            case LEFT: box.x+=(xVelocity - grav); break;
            case RIGHT: box.x+=(xVelocity + grav); break;
            case DOWN: box.y+=(yVelocity + grav); break;
            case UP: box.y+=(yVelocity - grav); break;
        }
    }

    return box;
}

void Unit::walk(Direction gravity_dir, Direction dir)
{
    switch(dir)
    {
        case UP: break;
        case DOWN: break;
        case RIGHT: facing_left = false; break;
        case LEFT: facing_left = true;
    }
    switch(gravity_dir)
    {
        case DOWN: break;
        case UP:
            if(dir == LEFT)
                dir = RIGHT;
            else if(dir == RIGHT)
                dir = LEFT;
            break;
        case LEFT:
            if(dir == LEFT)
                dir = UP;
            else if(dir == RIGHT)
                dir = DOWN;
            break;
        case RIGHT:
            if(dir == LEFT)
                dir = DOWN;
            else if(dir == RIGHT)
                dir = UP;
            break;
    }
    switch(dir)
    {
        case UP: yAcc = -1*speed; xAcc = 0;break;
        case DOWN: yAcc = speed; xAcc = 0;break;
        case LEFT: xAcc = -1*speed; yAcc = 0; break;
        case RIGHT: xAcc = speed; yAcc = 0; break;
    }
    img.incFrame();
}

void Unit::stand()
{
    xAcc = 0;
    yAcc = 0;
    img.setStanding(facing_left);
}

void Unit::jump(Direction dir)
{
    switch(dir)
    {
      case UP: yVelocity -= jump_dist; break;
      case RIGHT: xVelocity += jump_dist; break;
      case LEFT: xVelocity -= jump_dist; break;
      case DOWN: yVelocity += jump_dist; break;
    }
}
